//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2024 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

public import Foundation
public import LanguageServerProtocol

/// After a `taskStart` and before `taskFinish` for a `taskId`, the server may send any number of progress
/// notifications.
public struct TaskProgressNotification: NotificationType {
  public static let method: String = "build/taskProgress"

  /// Unique id of the task with optional reference to parent task id
  public var taskId: TaskId

  /// A unique identifier generated by the client to identify this request.
  public var originId: String?

  /// Timestamp of when the event started in milliseconds since Epoch.
  @CustomCodable<MillisecondsSince1970Date?>
  public var eventTime: Date?

  /// Message describing the task.
  public var message: String?

  /// If known, total amount of work units in this task.
  public var total: Int?

  /// If known, completed amount of work units in this task.
  public var progress: Int?

  /// Name of a work unit. For example, "files" or "tests". May be empty.
  public var unit: String?

  /// Kind of data to expect in the `data` field. If this field is not set, the kind of data is not specified.
  public var dataKind: TaskProgressDataKind?

  /// Optional metadata about the task.
  ///
  /// Objects for specific tasks like compile, test, etc are specified in the protocol.
  public var data: LSPAny?

  public init(
    taskId: TaskId,
    originId: String? = nil,
    eventTime: Date? = nil,
    message: String? = nil,
    total: Int? = nil,
    progress: Int? = nil,
    unit: String? = nil,
    dataKind: TaskProgressDataKind? = nil,
    data: LSPAny? = nil
  ) {
    self.taskId = taskId
    self.originId = originId
    self.eventTime = eventTime
    self.message = message
    self.total = total
    self.progress = progress
    self.unit = unit
    self.dataKind = dataKind
    self.data = data
  }
}

/// Task progress notifications may contain an arbitrary interface in their `data` field.
///
/// The kind of interface that is contained in a notification must be specified in the `dataKind` field.
public struct TaskProgressDataKind: RawRepresentable, Codable, Hashable, Sendable {
  public let rawValue: String
  public init(rawValue: String) {
    self.rawValue = rawValue
  }
}
